/* JSON.parse和JSON.stringify的使用 */

/**
 * JSON.parse(text,function)
 * 两个参数，一个text是需要处理的字符串
 * 一个是可选的转换器，可以修改解析成的原始值，调用时机在parse返回之前
 * */ 

var text = '{"name":"hetao","age":"3"}'

var obj = JSON.parse(text,function(v,k){
  // console.log(v,'------',k) 
  // name ------ hetao age------3 ------{}
})
// console.log(obj)  // undefined 因为没有返回

/**
 * JSON.stringify(value[, replacer [, space]]) 三个参数
 * 第一个参数需要处理value的值
 * 第二个参数是处理的函数，如果是一个数组，如果该参数是一个数组，则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中。不存在这个参数，所有属性都被序列化
 * 第三个参数是指定缩进用的空白字符串，用于美化输出
*/
JSON.stringify({ x: 1, y: 2 });

// "{"x":1,"y":2}"

JSON.stringify({ x: [10, undefined, function () { }, Symbol('')] })

// "{"x":[10,null,null,null]}"

/* 第二个参数的例子 */

function replacer(key, value) {

  if (typeof value === "string") {

    return undefined;

  }

  return value;

}

var foo = { foundation: "Mozilla", model: "box", week: 4, transport: "car", month: 7 };

// 第二个参数为函数
var jsonString = JSON.stringify(foo, replacer);

// console.log(jsonString); // "{"week":4,"month":7}"

// 第二个参数为数组
var newJSONStringify = JSON.stringify(foo, ['week','model'])
// console.log(newJSONStringify)  // {"week":4,"model":"box"}

/* 第三个参数的例子 */

var jsonString3=JSON.stringify({ a: 2 }, null, " ");

// console.log(jsonString3)
/* "{
 "a": 2
}"*/

JSON.stringify({ a: 2 }, null, "");

// "{"a":2}"


/**
 * JSON.stringify()函数的手写需要注意一些边界的情况
 * -------------------------------基本数据类型
 * undefined 输出undefined
 * false,true 输出"false","true"
 * null 输出 "null"
 * number 123 输出的是字符串类型的数值 '123'
 * string 'name' 输出还是string 'name'
 * NaN和Infinity 输出 'null'
 * -------------------------------引用数据类型
 * function 输出 undefined
 * symbol
 * Array [1,2,3] 输出 '[1, 2, 3]'
 * Array [function(){},undefined,null]  输出 '[null,null,null,null]'
 * RegExp new RegExp("\w") 输出 "{}"
 * Date() new Date()  输出Date 的toJSON()的字符串
 * 普通的object {name:'hehe',age: undefined, symbol: Symbol()}  输出 {"name":"hehe"}  属性值为undefined或者Symbol的不会输出
 * 普通object 带有toJSON()方法 {name:'hehe',age: undefined, symbol: Symbol(), toJSON(){return 123}}  直接输出toJSON方法返回的数据其他数据忽略
*/


var n1 = new RegExp("\w")
/** 
 * [1,2,3]  object string [1,2,3]   object string [1,2,3]
 * function function undefined undefined  function undefined undefined
 * Symbol() symbol undefined undefined symbol undefined undefined
 * new RegExp("\w") object string {} object string {}
 * */ 

console.log(typeof n1, typeof JSON.stringify(n1), JSON.stringify(n1))
console.log(typeof n1, typeof JSONStringify(n1), JSONStringify(n1))
function JSONStringify(data){
  let type = typeof data;
  if(type !=='object'){
    // 处理data为基本数据类型
    let result = data
    if(Number.isNaN(data) || data === Infinity){
      //NaN 和 Infinity 序列化返回 "null"
      result = "null"
    } else if (type === 'undefined' || type === 'function' || type === "symbol") {
      return undefined
    }else if (type==='string'){
      result = '"' + data + '"'
    }
    // number、boolean
    return String(result)
  }else if(type ==='object'){
    if(data === null){
      return "null"
    }else if(data.toJSON && typeof data.toJSON === 'function'){
      // 处理对象里边有toJSON函数的值
      return JSONStringify(data.toJSON)
    }else if(data instanceof Array){
      let result = []
      // data里边的每一项需要单独判断的
      data.forEach((item,index)=>{
        if (typeof item === 'undefined' || typeof item === 'function' || typeof item ==='symbol'){
          result[index] = "null"
        }else{
          //result[index] = '"'+item+'"'
          result[index] = JSONStringify(item)
        }
      })
      result = "[" + result + "]";
      return result.replace(/'/g, '"');
    }else{
      let result = []
      Object.keys(data).forEach((item,index)=>{
        console.log(data[item])
        if(typeof item != 'symbol') {
          // key的值是symbol，就忽略
          if(data[item] !==undefined || typeof data[item] !== 'function' || typeof data[item] !=='symbol'){
            result.push('"'+ item + '"' + ":" + JSONStringify(data[item]))
          }
        }
      })
      return ("{"+ result +"}").replace(/'/g,'"')
    }

  }
}
